function sensornet_server_file_processing

%%
% TODO: process_input_files() if there is an error
% in one file do not stop the whole processing
% TODO: JAVA_TS, MATLAB_TS format
% TODO: recover voltage from frequencies table


%% GLOBAL configuration
global INPUT_DIR; global AMR_DIR; global WAV_DIR; global DECODED_DIR; global DB_DIR;
global VERSION;
global AMR2WAV_TOOL;
global VOLTAGE_FORMAT;
global F6_INTERVAL; %seconds between 6-freqs

VOLTAGE_FORMAT='%4.4f';
AMR2WAV_TOOL = 'amr2wav.bat';
root_dir = 'WEB';
F6_INTERVAL = 1;


INPUT_DIR = [root_dir filesep 'INPUT'];
AMR_DIR = [root_dir filesep 'DATA' filesep 'AMR'];
WAV_DIR = [root_dir filesep 'DATA' filesep 'WAV'];
DECODED_DIR = [root_dir filesep 'DATA' filesep 'DECODED'];
DB_DIR = [root_dir filesep 'DATA' filesep 'DB'];

VERSION = 'Beta 1.0 Build/20101015';

%% MESSAGE
disp('###############');
disp('sensornet_server_file_processing');
disp(['Version:' VERSION]);


%% INTIALIZATION

if (isdir(root_dir))
    %disp('Exists')
else 
    disp('Creating default directory structure...')
    mkdir(root_dir);
    mkdir(INPUT_DIR);
    mkdir(AMR_DIR);
    mkdir(WAV_DIR);
    mkdir(DECODED_DIR);
    mkdir(DB_DIR);
end

%% Complete file processing
% process_input_files()
% update_DB_files();
%plot_decoded_DB();

%% Reprocessing

% clean_db_files('MOTE-64');
% clean_db_files('BMOTE-50');
% clean_db_files('MOTE-94');
%process_wav_files();
%update_DB_files();


% plot_DB('BMOTE');
% plot_decoded_DB();

% csv_fullname = 'WEB\DATA\DB\BMOTE\20100919.csv';
% generate_DB_file(csv_fullname);

plot_DB('G50');
plot_DB('G94');
plot_DB('g64');
% plot_decoded_DB();


%% END MESSAGE
disp('sensornet_server_file_processing:Done');

end

%% Main functions

function update_DB_files()
% Check if db files need an update and regenerate db files (*.dat)

global DB_DIR;
files_dir = DB_DIR;
files = dir(files_dir);
nfiles = size(files,1);
for i=1:nfiles
   %TODO: check directory
	filename = files(i).name;
    dir_fullname = fullfile(files_dir, filename);
    db_files = dir( fullfile(dir_fullname, '*.csv'));
    ndbfiles = size(db_files,1);
    for j=1:ndbfiles
        csv_fullname = fullfile(dir_fullname, db_files(j).name);
        %TODO: check if .csv is older than .dat
        updated_needed =1;
        dat_file = dir( [csv_fullname '.dat'] );
        if size(dat_file,1) >0
%         csv_fullname
%         db_files(j).datenum 
%         dat_file(1).datenum
            if (db_files(j).datenum <= dat_file(1).datenum)
                updated_needed = 0;
            end
        end

        if updated_needed
            disp(['udpated needed:' csv_fullname]);
            generate_DB_file(csv_fullname);
%         else 
%             disp('udpated NOT needed *****');
        end
    end
end


end

function process_input_files()
% process input files (*.amr) from INPUT_DIR 
% and generates *.wav, *.txt and yyyymmdd.csv
global INPUT_DIR;
global AMR_DIR;
global WAV_DIR;
global DECODED_DIR;
global DB_DIR;
files_dir = INPUT_DIR;
disp(['Processing input directory:', files_dir]);
files = dir([files_dir filesep '*.amr']);
nfiles = size(files,1);
for j=1:nfiles
	filename = files(j).name;
    file_fullname = [files_dir filesep filename];
    % parse metadata
    metadata = parse_metadata(filename);
    debugPercentage(j, nfiles,file_fullname);
    metadata.amr_filesize = 0;
    % AMR conversion to WAV
    wav_fullname = amr2wav(file_fullname, WAV_DIR, metadata.id);
    movefile(file_fullname, AMR_DIR);
    % FFT analysis
    decoded_fullname = decode_wav(wav_fullname, DECODED_DIR, metadata.id);
    % Add info to database
    add_to_DB(decoded_fullname, DB_DIR, metadata);
end

end

function process_wav_files()
% process *.wav from WAV_DIR and 
% regenerates *.txt and yyyymmdd.csv
global WAV_DIR;
global DECODED_DIR;
global DB_DIR;
files_dir = WAV_DIR;
disp(['Processing input directory:', files_dir]);
files = dir([files_dir filesep '*.wav']);
nfiles = size(files,1);
for j=1:nfiles    
	filename = files(j).name;
    file_fullname = [files_dir filesep filename];
    % parse metadata
    filename = strrep(filename, '.wav', '');
    metadata = parse_metadata(filename);
    debugPercentage(j, nfiles,file_fullname);
    wav_fullname = file_fullname;
    % FFT analysis
    decoded_fullname = decode_wav(wav_fullname, DECODED_DIR, metadata.id);
    %decoded_fullname = fullfile(DECODED_DIR, strcat(metadata.id, '.txt'));
   
    % Add info to database
    add_to_DB(decoded_fullname, DB_DIR, metadata);
end

end

function clean_db_files(sensor)
% Removes all the *.csv and *.dat files
global DB_DIR;
files_dir = fullfile(DB_DIR, sensor);
disp(['Cleaning DB files:', files_dir]);
delete([files_dir filesep '*.csv']);
delete([files_dir filesep '*.dat']);
end


%% Auxiliar functions

function metadata = parse_metadata(filename)
%Obtains timestamp information from filename

    % alpha_1276588493390.amr
    % <sensor_id>_ts.amr
    metadata.filename = filename;
    index1 = strfind(filename, '_');
    len = length(filename);
    metadata.sensor = filename(1:index1-1);
    index2 = strfind(filename, '.');
    metadata.timestamp = str2double(filename(index1+1:index2-1));
    metadata.extension = filename(index2+1 : len);
    metadata.id = filename;
    metadata.serial = javaMillis2serialDate(metadata.timestamp);
    metadata.date = datestr(metadata.serial, 'yyyymmdd');
    metadate.time = datestr(metadata.serial, 'HHMMSS');
end

function wav_fullname = amr2wav(file_fullname, output_dir, id)
% Converts an AMR file into a WAV file in the output_dir
    global AMR2WAV_TOOL;
	
    filename = strcat(id, '.wav');
    wav_fullname = fullfile(output_dir, filename);

    system( [AMR2WAV_TOOL ' ' file_fullname ' ' wav_fullname]);

	%disp(['  amr2wav done: ' file_fullname]);
end

function decoded_fullname = decode_wav(file_fullname, output_dir, id)
% Decodes the wav sound file and generates a TXT file in the output_dir
global VOLTAGE_FORMAT;
    [voltage, info] = decode_single_frequency_wav(file_fullname);
    
    filename = strcat(id, '.txt');
    decoded_fullname = fullfile(output_dir, filename);
    fid = fopen(decoded_fullname, 'w+');
    fprintf(fid, '%s\n', ['filename :' id]);
    fprintf(fid, [VOLTAGE_FORMAT '\n'], voltage);
    fprintf(fid, '%i ', info);
    fclose(fid);
	%disp(['  decode_wav done: ' file_fullname]);
end

function add_to_DB(decoded_fullname, db_dir, metadata)
% Appends the information from decoded file to the DB file (*.csv)
% mode='a' => appends the information
% mode='w' => ovewrite the information
global VOLTAGE_FORMAT;
global F6_INTERVAL;
	data = textread(decoded_fullname, '%s', 'delimiter', ' ');
    %%%t = str2double(data{2}(8:20));
    %%%serial_date = javaMillis2serialDate(t);
    t = metadata.timestamp;
    serial_date = metadata.serial;
    f = str2double(data{3});
    f6 = [str2double(data{4}) str2double(data{5}) str2double(data{6}) str2double(data{7}) str2double(data{8}) str2double(data{9}) ];
    sensor_id = metadata.sensor;
    %%%filename = datestr(serial_date, 'yyyymmdd');
    filename = metadata.date;
    
    db_dir = fullfile(db_dir, sensor_id);
    
    
    [s,mess,messid] = mkdir(db_dir);
    if (s == 0)
        disp('ERROR');
        disp (mess);
    end
    output_fullname = fullfile(db_dir, [filename '.csv']);
%    output_fullname = fullfile(db_dir, sensor_id, filename)
% %     fid = fopen(output_fullname, 'a');
% %     fprintf(fid, '%s', datestr(serial_date,'dd/mm/yyyy'));
% %     fprintf(fid, '\t%s', datestr(serial_date,'HH:MM'));
% %     fprintf(fid, '\t%3.1f', f);
% %     fprintf(fid, '\t%.0f\n', t);
% %     fclose(fid);
    fid = fopen(output_fullname, 'a');
%     fprintf(fid, '%.0f', t);
%     fprintf(fid, [',' VOLTAGE_FORMAT], f);
%     fprintf(fid, ',%f\n', serial_date);
    seconds_per_day = 24*3600;
    for i=length(f6):-1:1
        ff = f6(i);
        dd = serial_date - i*F6_INTERVAL/seconds_per_day;
        tt = t - i*F6_INTERVAL * 1000;
        fprintf(fid, '%.0f', tt);
        fprintf(fid, [',' VOLTAGE_FORMAT], ff);
        fprintf(fid, ',%f\n', dd);
    end
    fclose(fid);
    %%generate_DB_file(output_fullname);
end

function generate_DB_file(file_fullname)
% Read the yyyymmdd.csv file, time-order the rows
% and (over)writes the yyyymmdd.dat 

global VERSION;
global VOLTAGE_FORMAT;
%	data = textread(file_fullname, '%s', 'delimiter', '\t')
    data = csvread(file_fullname);
    sdata = sortrows(data,1);
    nitems = size(data,1);
    output_fullname =  [file_fullname '.dat'];
    fid = fopen(output_fullname, 'w');
    fprintf(fid, '%s\n', strcat('VERSION: ', VERSION, ' FILE:', file_fullname) );
    fprintf(fid, '%s\n', 'dd/mm/yyyy HH:MM:SS VOLTAGE JAVA_TS MATLAB_TS ');
    last_ts = 0;
    for i=1:nitems
        row = data(i,:);
        ts = row(1);
        if (ts> last_ts)
            % if not repeated, print row data
            %%06/09/2010 0:00:00            1.733
            format_ts = datestr(row(3), 'dd/mm/yyyy HH:MM:SS');
            fprintf(fid, '%s', format_ts); 
            fprintf(fid, [' ' VOLTAGE_FORMAT], row(2)); %vol
            fprintf(fid, ' %.0f', row(1));
            fprintf(fid, ' %f\n', row(3));
            last_ts = ts;
        end
    end
    fclose(fid);
end


%% Graph functions

function plot_DB(sensor)
% Generates a graph for the sensor with the DB *.dat files
    global DB_DIR;
    files_dir = fullfile(DB_DIR, sensor);
    files = dir([files_dir filesep '*.dat']);
    nfiles = size(files,1);
    t = [];
    f = [];
    for j=1:nfiles
    	filename = files(j).name;
        file_fullname = fullfile(files_dir, filename);
        data = textread(file_fullname, '%s', 'delimiter', '\n');
        nlines = size(data,1);
        for i=3:nlines
            line = data{i};
            % dd/mm/yyyy HH:MM:SS VOLTAGE JAVA_TS MATLAB_TS
            index = strfind(line, ' ');
            % date 1 index1
            % time index1 index2
            value = line(index(2)+1 : index(3)-1);
            ts = line(index(3)+1:index(4)-1);
            serial = line(index(4)+1 : length(line) );
            t = [t str2double(serial)];
            f = [f str2double(value)];
        end
    end
    h = figure('Name', ['Sensor: ' sensor] );
    plot(t, f, '-.or', 'color', 'r');
    ylabel('Voltage');


%     f = f*600+500;%v = (freq-500) * 5 /3000;
%     plot(t, f, '-.or', 'color', 'r');
%     ylabel('Frequency (Hz)');


%     f_round = round(f/5)*5;
% 
%     plot(t, f-f_round, 'o', 'color', 'b');
%     ylabel('Error: f - round(f/5)*5');
    
    title(['Sensor: ' sensor] );
    grid on;
    seconds_per_day = 24*60*60;
    seconds_per_tick = 20;
    tt = t(1) + [1:seconds_per_tick:seconds_per_tick*180] / seconds_per_day;
%    tt = tt - 3/seconds_per_day;
%    set(gca,'XTick',tt)
    datetick('x','HH:MM','keepticks')
    
% % second axis
% ax1 = gca;
% ax2 = axes('Position',get(ax1,'Position'), 'XAxisLocation','top', ...
%     'YAxisLocation','right','Color','none','YColor','k');
% set(ax2, 'XLim', [0,1]);       
% set(ax2, 'XTick', [0]);
% set(ax1, 'YLim', [0, 5]);       
% set(ax2, 'YLim', [500, 3000]);       
% set(get(gca,'YLabel'),'String','Frequency (Hz)')

    
    
end


function plot_decoded_DB()
% Generates a graph with the information of 
% the files in the DECODED_DIR

    global DECODED_DIR;
    global t;
    global f;
    files_dir = DECODED_DIR;
    files = dir([files_dir filesep '*.txt']);
    nfiles = size(files,1);
    t = [];
    v = [];
    f = [];
    for j=1:nfiles
    	filename = files(j).name;
        file_fullname = [files_dir filesep filename];
        data = textread(file_fullname, '%s', 'delimiter', ' ');
        t = [t str2double(data{2}(8:20)) ];
        v = [v str2double(data{3}) ];
        f = [f str2double(data{4}) ];
    end
    t = javaMillis2serialDate(t);
    h = figure('Name', 'Voltage: Decoded DIR files');
    plot(t, v, '-ob');
    seconds_per_day = 24*60*60;
    seconds_per_tick = 120;
    tt = t(1) + [1:seconds_per_tick:seconds_per_tick*18] / seconds_per_day;
%    tt = tt - 3/seconds_per_day;
%    set(gca,'XTick',tt)
    datetick('x','HH:MM:SS','keepticks')
%    datetick('x','HH:MM','keepticks')
    grid on

    h = figure('Name', 'Freq: Decoded DIR files');
    plot(t, f, '-ob');
    datetick('x','HH:MM:SS','keepticks')
%    datetick('x','HH:MM','keepticks')
    grid on
    
    

end

%% Utility functions

function serial_date = javaMillis2serialDate(millis)
    % serial date: number of days since d1 is January 1, 0000
    % java millis: number of milliseconds since January 1, 1970, 00:00:00 GMT 
    serial_date = datenum('01-01-1970 00:00', 'dd-mm-yyyy HH:MM');
    millis_per_day = (1000*3600*24);
    utc_correction = 2 * 3600 * 1000; % +2hours
    millis = millis + utc_correction;
    serial_date = serial_date + millis/millis_per_day;
end

function debugPercentage(current, total, message)
points = 20;
step = floor(total/points);
if (mod(current, step)==0)
    status = floor(current/total*100);
    disp(['Processing...:' num2str(status) '% ' num2str(current) '/' num2str(total) ' ' message]);
    end
end
